package com.xg.sql.ast;

import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;
import com.alibaba.druid.sql.parser.*;
import com.alibaba.druid.util.FnvHash;

public class AstTest {
    private static Lexer lexer;
    private static MySqlExprParser mySqlExprParser;
    private static String dbType;

    public static void main(String[] args) {
        //String sql = "select a, b, cast(c as string) ,1.5+10 from user";
        String sql = "select a + b * 5 from t_user ";
        mySqlExprParser = new MySqlExprParser(sql);
        lexer = mySqlExprParser.getLexer();
        dbType = lexer.getDbType();
        SQLExprParser exprParser = SQLParserUtils.createExprParser("a + (b * 5) + (2+1) ", dbType);
        exprParser.parseSelectItem();
        if (true) {
            return;
        }
        SQLUtils.parseStatements(sql, dbType);

        Token token = lexer.token();
        printToken(token);
        if (token == Token.SELECT) {
            SQLSelect select = parseSelect();
            System.out.println(SQLUtils.toSQLString(select, lexer.getDbType()));
        } else {
            throw new RuntimeException("只支持select语句");
        }
    }

    private static void printToken(Token token) {
        Keywords keywods = lexer.getKeywods();
        long l = FnvHash.fnv1a_64_lower(token.name());
        Token keyword = keywods.getKeyword(l);
        if (keyword != null) {
            System.out.println(token.name() + "\t\t" + lexer.stringVal() + "\tis keyword");
        } else if (token == Token.IDENTIFIER) {
            System.out.println(token.name() + "\t\t" + lexer.stringVal());
        } else if (token == Token.SELECT) {
            System.out.println(token.name() + "\t\t" + lexer.stringVal());
        } else if (token == Token.COMMA) {
            System.out.println(token.name() + "\t\t" + ",");
        } else if (token == Token.LPAREN) {
            System.out.println(token.name() + "\t\t" + "(");
        } else if (token == Token.RPAREN) {
            System.out.println(token.name() + "\t\t" + ")");
        } else if (token == Token.LITERAL_FLOAT || token == Token.LITERAL_INT) {
            System.out.println(token.name() + "\t\t" + lexer.numberString());
        } else if (token == Token.PLUS) {
            System.out.println(token.name() + "\t\t" + "+");
        } else {
            System.out.println(token);
        }
    }

    private static SQLSelect parseSelect() {
        SQLSelect select = new SQLSelect();
        except(Token.SELECT);
        SQLSelectQuery selectQuery = parseQuery();
        selectQuery.setParent(select);
        select.setQuery(selectQuery);
        return select;
    }

    private static SQLSelectQuery parseQuery() {
        Token token = lexer.token();
        printToken(token);

        SQLSelectQueryBlock queryBlock = new SQLSelectQueryBlock(dbType);

        parseSelecItem(queryBlock);

        except(Token.FROM);
        SQLTableSource sqlTableSource = parseFrom();
        queryBlock.setFrom(sqlTableSource);

        return queryBlock;
    }

    private static void parseSelecItem(SQLSelectQueryBlock queryBlock) {
        for (; ; ) {
            Token token = lexer.token();
            SQLExpr expr = null;
            if (token == Token.IDENTIFIER) {
                String preName = lexer.stringVal();
                expr = new SQLIdentifierExpr(preName);
            } else if (token == Token.LITERAL_INT || token == Token.LITERAL_FLOAT) {

            } else if (token == Token.LPAREN) {
                //结束为右括号
                except(Token.RPAREN);
            }

            lexer.nextToken();
            token = lexer.token();

            if (token == Token.COMMA) {
                SQLSelectItem sqlSelectItem = new SQLSelectItem(expr);
                queryBlock.addSelectItem(sqlSelectItem);
                lexer.nextToken();
                continue;
                //逗号
            } else if (token == Token.LPAREN) {
                //左括号
                //结束为右括号
                except(Token.RPAREN);
            } else if (token == Token.AS) {
                //as 关键字
            } else if (token == Token.PLUS || token == Token.SUB || token == Token.STAR || token == Token.SLASH) {
                // 加减乘除
                SQLBinaryOpExpr sqlBinaryOpExpr = new SQLBinaryOpExpr();
                sqlBinaryOpExpr.setLeft(expr);
                lexer.nextToken();
                token = lexer.token();

            }

            SQLSelectItem sqlSelectItem = new SQLSelectItem(expr);
            queryBlock.addSelectItem(sqlSelectItem);
            if (token != Token.COMMA) {
                break;
            }
        }
    }

    private static SQLTableSource parseFrom() {
        Token token = lexer.token();
        if (token == Token.IDENTIFIER) {
            String preName = lexer.stringVal();
            SQLExprTableSource sqlExprTableSource = new SQLExprTableSource(new SQLIdentifierExpr(preName));
            return sqlExprTableSource;
        }
        return null;
    }

    private static void except(Token except) {
        if (except == lexer.token()) {
            lexer.nextToken();
        } else {
            throw new RuntimeException("希望token为" + except.name() + "但是token：为" + lexer.token());
        }
    }

}
